package com.whc.gulimall.member.service.impl;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.whc.common.utils.PageUtils;
import com.whc.common.utils.Query;
import com.whc.common.utils.RRException;
import com.whc.gulimall.member.dao.MemberDao;
import com.whc.gulimall.member.entity.MemberEntity;
import com.whc.gulimall.member.entity.MemberLoginLogEntity;
import com.whc.gulimall.member.exception.PhoneExistsException;
import com.whc.gulimall.member.exception.UsernameExistsException;
import com.whc.gulimall.member.service.MemberLevelService;
import com.whc.gulimall.member.service.MemberLoginLogService;
import com.whc.gulimall.member.service.MemberService;
import com.whc.gulimall.member.vo.LoginVo;
import com.whc.gulimall.member.vo.RegisterVo;
import com.whc.gulimall.member.vo.SocialUserVo;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Map;


@Service("memberService")
public class MemberServiceImpl extends ServiceImpl<MemberDao, MemberEntity> implements MemberService {

    /**
     * 会员等级 Service
     */
    @Resource
    private MemberLevelService memberLevelService;

    /**
     * 会员登录记录
     */
    @Resource
    private MemberLoginLogService memberLoginLogService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<MemberEntity> page = this.page(
                new Query<MemberEntity>().getPage(params),
                new QueryWrapper<>()
        );

        return new PageUtils(page);
    }

    /**
     * 注册
     *
     * @param vo vo
     */
    @Override
    public void register(RegisterVo vo) {
        MemberEntity memberEntity = new MemberEntity();

        // 查询并设置等级
        Long defaultLevel = memberLevelService.getDefaultLevel();
        memberEntity.setLevelId(defaultLevel);

        // 查重
        checkPhoneIsExists(vo.getPhone());
        checkUsernameIsExists(vo.getUsername());

        // 设置
        memberEntity.setMobile(vo.getPhone());
        memberEntity.setUsername(vo.getUsername());

        // 加密密码
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        memberEntity.setPassword(bCryptPasswordEncoder.encode(vo.getPassword()));

        // 保存
        baseMapper.insert(memberEntity);
    }


    /**
     * 检查手机号是否已经存在
     *
     * @param phone 手机号
     * @throws PhoneExistsException 手机号存在异常
     */
    @Override
    public void checkPhoneIsExists(String phone) throws PhoneExistsException {
        if (baseMapper.selectCount(new QueryWrapper<MemberEntity>().eq("mobile", phone)) > 0) {
            throw new PhoneExistsException();
        }
    }

    /**
     * 检查用户名是否已经存在
     *
     * @param username 用户名
     * @throws UsernameExistsException 用户名存在异常
     */
    @Override
    public void checkUsernameIsExists(String username) throws UsernameExistsException {
        if (baseMapper.selectCount(new QueryWrapper<MemberEntity>().eq("username", username)) > 0) {
            throw new UsernameExistsException();
        }
    }

    /**
     * 登录
     *
     * @param vo vo
     */
    @Override
    public void login(LoginVo vo) {
        MemberEntity memberEntity = baseMapper.selectOne(new QueryWrapper<MemberEntity>().eq("username", vo.getUsername())
                .or().eq("mobile", vo.getUsername()));
        if (memberEntity != null) {
            BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
            // 密码匹配
            if (bCryptPasswordEncoder.matches(vo.getPassword(), memberEntity.getPassword())) {
                // 记录登录历史
                MemberLoginLogEntity loginLogEntity = new MemberLoginLogEntity();
                loginLogEntity.setMemberId(memberEntity.getId());
                loginLogEntity.setCreateTime(new Date());
                loginLogEntity.setLoginType(1);
                memberLoginLogService.save(loginLogEntity);
            } else {
                throw new RRException("密码错误");
            }
        } else {
            throw new RRException("用户不存在");
        }
    }

    /**
     * oauth2登录
     *
     * @param socialUserVo 社交用户登录
     * @return 获取数据
     */
    @Override
    public MemberEntity oauthTwoLogin(@RequestBody SocialUserVo socialUserVo) throws RRException {
        // 先查询是否已经在数据库中存在
        MemberEntity memberEntity = baseMapper
                .selectOne(new QueryWrapper<MemberEntity>().eq("uid", socialUserVo.getUid()));

        // 不是第一次登录
        if (memberEntity != null) {
            memberEntity.setAccessToken(socialUserVo.getAccessToken());
            memberEntity.setExpiresIn(socialUserVo.getExpiresIn());
            baseMapper.updateById(memberEntity);
        } else {
            // 第一次登录
            // 通过uid作为参数调用接口
            try {
                HttpResponse response = HttpRequest.get("https://api.weibo.com/2/users/show.json?" + "access_token="
                        + socialUserVo.getAccessToken() + "&uid=" + socialUserVo.getUid()).execute();
                // 调用成功
                if (response.getStatus() == 200) {
                    // 获取对象成功
                    JSONObject jsonObject = JSON.parseObject(response.body());
                    memberEntity = new MemberEntity();
                    memberEntity.setNickname((String) jsonObject.get("name"));
                    memberEntity.setHeader((String) jsonObject.get("avatar_hd"));
                    memberEntity.setGender("m".equals(jsonObject.get("gender")) ? 1 : 0);
                    memberEntity.setAccessToken(socialUserVo.getAccessToken());
                    memberEntity.setExpiresIn(socialUserVo.getExpiresIn());
                    memberEntity.setUid(Long.parseLong(socialUserVo.getUid()));
                    baseMapper.insert(memberEntity);
                } else {
                    throw new RRException("调用远程接口失败");
                }
            } catch (Exception e) {
                throw new RRException("调用远程接口失败");
            }
        }

        return memberEntity;
    }

}
